package ai.people.netmon.msgsearch.service.impl;

import ai.people.core.common.properties.elastic.ElasticUserIndex;
import ai.people.netmon.framework.domain.searchmsg.request.SearchAccountRequest;
import ai.people.netmon.framework.domain.searchmsg.vo.SearchAccountVO;
import ai.people.netmon.framework.model.response.PageResponse;
import ai.people.netmon.msgsearch.service.AccountSearchService;
import ai.people.netmon.utils.StringPool;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 账户查询服务impl
 *
 * @author yuanqinglong
 * @date 2022/8/4 10:38
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AccountSearchServiceImpl implements AccountSearchService {


    private final RestHighLevelClient elasticsearchClient;

    /**
     * 搜索账户
     *
     * @param searchAccountRequest 搜索帐户请求
     * @return {@link PageResponse}<{@link SearchAccountVO}>
     */
    @Override
    public PageResponse<SearchAccountVO> searchAccount(SearchAccountRequest searchAccountRequest) throws IOException {
        SearchRequest searchRequest = buildRequest(searchAccountRequest);
        // 索引
        SearchSourceBuilder sourceBuilder = searchRequest.source();
        if (!StringUtils.isEmpty(searchAccountRequest.getSearchKeywords())) {
            MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(searchAccountRequest.getSearchKeywords(), "id", "user_name");
            sourceBuilder.query(multiMatchQueryBuilder);
        }
        searchRequest.source(sourceBuilder);
        log.info("检索语句 {}", searchRequest.source().toString());
        sourceBuilder.from(searchAccountRequest.getPageNo()).size(searchAccountRequest.getPageSize());
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        return this.pageResponse(searchResponse);
    }


    /**
     * 搜索标签帐户
     *
     * @param searchAccountRequest 搜索帐户请求
     * @return {@link PageResponse}<{@link SearchAccountVO}>
     * @throws Exception 异常
     */
    @Override
    public PageResponse<SearchAccountVO> searchLabelAccount(SearchAccountRequest searchAccountRequest) throws Exception {
        SearchRequest searchRequest = buildRequest(searchAccountRequest);
        SearchSourceBuilder searchSourceBuilder = searchRequest.source();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 查询被打了标签的账号
        boolQueryBuilder.must(QueryBuilders.wildcardQuery("tag.tag", "*"));
        if (!StringUtils.isEmpty(searchAccountRequest.getSearchKeywords())) {
            boolQueryBuilder.must(QueryBuilders.multiMatchQuery(searchAccountRequest.getSearchKeywords(), "id", "user_name", "nick_name",  "description"));
        }
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        log.info("预警账号检索语句 {}", searchRequest.source().toString());
        searchSourceBuilder.from(searchAccountRequest.getPageNo()).size(searchAccountRequest.getPageSize());
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        return this.pageResponse(searchResponse);
    }


    /**
     * 构建请求
     *
     * @param searchAccountRequest 搜索帐户请求
     * @return {@link SearchRequest}
     */
    private static SearchRequest buildRequest(SearchAccountRequest searchAccountRequest) {
        // 查询ES
        SearchRequest searchRequest;
        if (StringUtils.isEmpty(searchAccountRequest.getPlatform())) {
            searchRequest = new SearchRequest(ElasticUserIndex.getAllIndex());
        } else {
            String[] split = searchAccountRequest.getPlatform().split(StringPool.COMMA);
            String[] platforms = new String[split.length];
            for (int i = 0; i < split.length; i++) {
                platforms[i] = ElasticUserIndex.getOriginIndexName(split[i]);
            }
            searchRequest = new SearchRequest(platforms);
        }
        return searchRequest;
    }


    /**
     * 页面响应
     *
     * @param search 搜索
     * @return {@link PageResponse}<{@link Map}<{@link String}, {@link Object}>>
     */
    public PageResponse<SearchAccountVO> pageResponse(SearchResponse search) {
        if (Objects.isNull(search) || Objects.isNull(search.getHits())) {
            return PageResponse.builderEmpty();
        }
        SearchHits hits = search.getHits();
        TotalHits totalHits = hits.getTotalHits();
        SearchHit[] searchHits = hits.getHits();
        List<SearchAccountVO> list = Arrays.stream(searchHits).map(SearchHit::getSourceAsString).map(s -> JSON.parseObject(s, SearchAccountVO.class)).collect(Collectors.toList());
        return PageResponse.builder(list, totalHits.value);
    }
}
